<?php

namespace fize\think\session\driver;

use think\contract\SessionHandlerInterface;
use think\facade\Db;
use think\helper\Arr;

/**
 * ThinkPHP版本MySQL数据库方式Session管理器
 */
class MySQL implements SessionHandlerInterface
{
    /**
     * @var array
     */
    private $config;

    /**
     * @var int 有效时间
     */
    private $expire;

    /**
     * @var string 前缀
     */
    private $prefix;


    /**
     * 构造
     * @param array $config
     */
    public function __construct(array $config = [])
    {
        $this->config = $config;
        $this->expire = Arr::get($config, 'expire', 1440);
        $this->prefix = Arr::get($config, 'prefix', '');
    }

    /**
     * 打开session
     * @param string $save_path    保存路径
     * @param string $session_name session名称
     * @return bool
     */
    public function open(string $save_path, string $session_name): bool
    {
        return true;
    }

    /**
     * 关闭session
     * @return bool
     */
    public function close(): bool
    {
        $this->gc($this->expire);
        return true;
    }

    /**
     * 读取Session
     * @param string $sessionId sessionID
     * @return string
     */
    public function read(string $sessionId): string
    {
        $row = Db::name($this->config['tablename'])
            ->where([
                ['id', '=', $this->prefix . $sessionId],
                ['expire', '>', time()]
            ])
            ->findOrEmpty();
        if ($row) {
            return $row['data'];
        } else {
            return '';
        }
    }


    /**
     * 写入Session
     * @param string $sessionId sessionID
     * @param string $data      数据
     * @return bool
     */
    public function write(string $sessionId, string $data): bool
    {
        $res = Db::name($this->config['tablename'])->where(['id' => $this->prefix . $sessionId])->findOrEmpty();

        if ($res) {
            Db::name($this->config['tablename'])
                ->where(['id' => $this->prefix . $sessionId])
                ->update(['expire' => time() + $this->expire, 'data' => $data]);
        } else {
            $data = [
                'id'     => $this->prefix . $sessionId,
                'expire' => time() + $this->expire,
                'data'   => $data
            ];
            Db::name($this->config['tablename'])->insert($data, true);
        }

        return true;
    }


    /**
     * 删除Session
     * @param string $sessionId
     * @return bool
     */
    public function delete(string $sessionId): bool
    {
        Db::name($this->config['tablename'])->where('id', '=', $this->prefix . $sessionId)->delete();
        return true;
    }


    /**
     * 垃圾回收Session
     * @param int $maxlifetime 最大生命时间
     * @return bool
     */
    public function gc(int $maxlifetime): bool
    {
        Db::name($this->config['tablename'])->where('expire', '<', time())->delete();
        return true;
    }
}
